package com.clickhouse.demo.controller;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.clickhouse.demo.entity.ExampleTable;
import com.clickhouse.demo.service.ExampleTableService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 控制器
 * 测试mybatis-plus对clickhouse单表的简单操作
 * <p>
 * 主要是查插
 * 删改网上都说需要alter table来实现, 但是我使用下面这些还是可以执行成功,
 * 不知道为啥, jdbc的问题吗?还是数据库输配了, 或者说引擎的问题?
 *
 * @author codor
 * @date 2023/08/17 11:37
 */
@RestController
@RequiredArgsConstructor
public class ExampleTableController {

    private final ExampleTableService tableService;

    /**
     * 新增单个
     */
    @RequestMapping("/add")
    public String add() {
        ExampleTable table = ExampleTable.builder()
                .equipmentNum("A-YS-0" + RandomUtil.randomNumbers(2))
                .equipmentType("total_table")
                .logType("real_time_status")
                .logType("{\"equipmentNum\":\"A-YS-01\",\"run\":0,\"ready\":1,\"timeout\":0,\"fault\":1,\"leak\":0,\"overheat\":1,\"connectionStatus\":1,\"updateTime\":1692003525888,\"runTime\":1.242,\"remote\":1}")
                .build();
        tableService.save(table);
        return JSONUtil.toJsonStr(table);
    }

    /**
     * 批量新增, 9千万条数据做基础数据
     * 耗时约53分钟, 可以换成多线程异步来造数据
     */
    @RequestMapping("/addBatch")
    public void addBatch() {
        for (int j = 0; j < 9000; j++) {
            List<ExampleTable> saveList = new ArrayList<>();
            for (int i = 0; i < 1000; i++) {
                saveList.add(ExampleTable.builder()
                        .equipmentNum("A-YS-0" + RandomUtil.randomNumbers(2))
                        .equipmentType("total_table")
                        .logType("real_time_status")
                        .logType("{\"equipmentNum\":\"A-YS-0" + RandomUtil.randomNumbers(2) +
                                "\",\"run\":" + RandomUtil.randomInt(0, 1) +
                                ",\"ready\":"  + RandomUtil.randomInt(0, 1) +
                                ",\"timeout\":" + RandomUtil.randomInt(0, 1) +
                                ",\"fault\":" + RandomUtil.randomInt(0, 1) +
                                ",\"leak\":" + RandomUtil.randomInt(0, 1) +
                                ",\"overheat\":1,\"connectionStatus\":1,\"updateTime\":1692003525888,\"runTime\":1.242,\"remote\":1}")
                        .build());
            }
            tableService.saveBatch(saveList);
        }
    }

    /**
     * 分页查询, 测试limit(create_time设置的主键, 用create_time排序, 没有设置任何索引)
     * 只排序耗时(1百万页, 页面大小20): 110毫秒左右
     * 添加条件筛选耗时(1千页, 页面大小20): 930毫秒左右
     */
    @RequestMapping("/page")
    public Page<ExampleTable> page() {
        // 因为id不是递增, 所以使用时间来排序
        // 但是时间也有可能重复(即便带上毫秒), 所以加上id
        return tableService
                .lambdaQuery()
                .eq(ExampleTable::getEquipmentNum, "A-YS-072")
                .orderByDesc(ExampleTable::getCreateTime)
                .orderByDesc(ExampleTable::getId)
                .page(Page.of(1000 * 1000, 20));
    }

    /**
     * 统计, 测试group by
     * 耗时: 230毫秒左右
     */
    @RequestMapping("count")
    public Map<String, Integer> count() {
        return tableService
                .query()
                .select("equipment_num", "count(id) as num")
                .groupBy("equipment_num")
                .orderByAsc("equipment_num")
                .list()
                .stream()
                .collect(Collectors.toMap(ExampleTable::getEquipmentNum, ExampleTable::getNum));
    }

    // ----------------------------------------------------------------------------------------------------

    @RequestMapping("/update")
    public String update() {
        ExampleTable table = ExampleTable.builder()
                .id("003db989a2f79fe5c863ff88e480901a")
                .equipmentNum("自定义名称" + RandomUtil.randomString(2))
                .build();
        this.tableService.updateById(table);
        return JSONUtil.toJsonStr(table);
    }

    @RequestMapping("/delete")
    public boolean delete() {
        return this.tableService.removeById("003db989a2f79fe5c863ff88e480901a");
    }
}
